<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xeokit Example</title>
    <link href="../css/pageStyle.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>

    <style>

        /* ----------------------------------------------------------------------------------------------------------*/
        /* TreeViewPlugin */
        /* ----------------------------------------------------------------------------------------------------------*/

        #treeViewContainer {
            pointer-events: all;
            height: 100%;
            overflow-y: scroll;
            overflow-x: hidden;
            position: absolute;
            background-color: rgba(255, 255, 255, 0.2);
            color: black;
            top: 80px;
            z-index: 200000;
            float: left;
            left: 0;
            padding-left: 10px;
            font-family: 'Roboto', sans-serif;
            font-size: 15px;
            user-select: none;
            -ms-user-select: none;
            -moz-user-select: none;
            -webkit-user-select: none;
            width: 350px;
        }

        #treeViewContainer ul {
            list-style: none;
            padding-left: 1.75em;
            pointer-events: none;
        }

        #treeViewContainer ul li {
            position: relative;
            width: 500px;
            pointer-events: none;
            padding-top: 3px;
            padding-bottom: 3px;
            vertical-align: middle;
        }

        #treeViewContainer ul li a {
            background-color: #eee;
            border-radius: 50%;
            color: #000;
            display: inline-block;
            height: 1.5em;
            left: -1.5em;
            position: absolute;
            text-align: center;
            text-decoration: none;
            width: 1.5em;
            pointer-events: all;
        }

        #treeViewContainer ul li a.plus {
            background-color: #ded;
            pointer-events: all;
        }

        #treeViewContainer ul li a.minus {
            background-color: #eee;
            pointer-events: all;
        }

        #treeViewContainer ul li a:active {
            top: 1px;
            pointer-events: all;
        }

        #treeViewContainer ul li span:hover {
            color: white;
            cursor: pointer;
            background: black;
            padding-left: 2px;
            pointer-events: all;
        }

        #treeViewContainer ul li span {
            display: inline-block;
            width: calc(100% - 50px);
            padding-left: 2px;
            pointer-events: all;
            height: 23px;
        }

        #treeViewContainer .highlighted-node { /* Appearance of node highlighted with TreeViewPlugin#showNode() */
            border: black solid 1px;
            background: yellow;
            color: black;
            padding-left: 1px;
            padding-right: 5px;
            pointer-events: all;
        }

    </style>

</head>
<body>
<input type="checkbox" id="info-button"/>
<label for="info-button" class="info-button"><i class="far fa-3x fa-question-circle"></i></label>
<canvas id="myCanvas"></canvas>
<div id="treeViewContainer"></div>
<div class="slideout-sidebar">
    <img class="info-icon" src="../../assets/images/performance_model_icon.png"/>
    <h1>Loading federated models using SceneModel and MetaModel</h1>
    <p>In this example, we're programmatically building a simple federated model using two SceneModels and
        two MetaModels.</p>
    <p>One SceneModel contains an object for the table's top, while the other SceneModel contains four objects for the table's legs. </p>
    <p>One MetaModel contains MetaObjects for the table and the table top. The second MetaModel contains MetaObjects for the table, the table top, and each of the table legs.</p>
    <p>When we create these two MetaModels, they will automatically re-use the same MetaObject instances for the table and the table top.</p>

    <h3>Components Used</h3>
    <ul>
        <li>
            <a href="../../docs/class/src/viewer/Viewer.js~Viewer.html"
               target="_other">Viewer</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/metadata/MetaScene.js~MetaScene.html"
               target="_other">MetaScene</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/model/SceneModel.js~SceneModel.html"
               target="_other">SceneModel</a>
        </li>
        <li>
            <a href="../../docs/class/src/plugins/TreeViewPlugin/TreeViewPlugin.js~TreeViewPlugin.html"
               target="_other">TreeViewPlugin</a>
        </li>
    </ul>
</div>
</body>

<script type="module">

    //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {
        Viewer,
        SceneModel,
        TreeViewPlugin
    } from "../../dist/xeokit-sdk.min.es.js";

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer and arrange the camera
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true
    });

    viewer.scene.camera.eye = [-21.80, 4.01, 6.56];
    viewer.scene.camera.look = [0, -5.75, 0];
    viewer.scene.camera.up = [0.37, 0.91, -0.11];

    viewer.cameraFlight.fitFOV = 35;

    viewer.scene.highlightMaterial.edgeColor = [0, 0, 0];

    //------------------------------------------------------------------------------------------------------------------
    // First geometry model, containing table legs
    //------------------------------------------------------------------------------------------------------------------

    const sceneModel1 = new SceneModel(viewer.scene, {
        id: "furniture1",
        isModel: true, // <--------------------- Represents a model, registers SceneModel by ID on viewer.scene.models
        position: [0, 0, 0],
        scale: [1, 1, 1],
        rotation: [0, 0, 0],
        edges: true
    });

    sceneModel1.createGeometry({
        id: "myBoxGeometry",
        primitive: "triangles",
        positions: [
            1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front
            1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v1 right
            1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v1-v6-v1 top
            -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left
            -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1,// v7-v4-v3-v2 bottom
            1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v1 back
        ],
        normals: [
            0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,// v0-v1-v2-v3 front
            1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,// v0-v3-v4-v5 right
            0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,// v0-v5-v6-v1 top
            -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,// v1-v6-v7-v2 left
            0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,// v7-v4-v3-v2 bottom
            0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1// v4-v7-v6-v5 back
        ],
        indices: [
            0, 1, 2, 0, 2, 3,            // front
            4, 5, 6, 4, 6, 7,            // right
            8, 9, 10, 8, 10, 11,         // top
            12, 13, 14, 12, 14, 15,      // left
            16, 17, 18, 16, 18, 19,      // bottom
            20, 21, 22, 20, 22, 23
        ]
    });

    sceneModel1.createMesh({
        id: "redLegMesh",
        geometryId: "myBoxGeometry",
        position: [-4, -6, -4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
        color: [1, 0.3, 0.3]
    });

    sceneModel1.createEntity({
        id: "redLeg",
        meshIds: ["redLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel1.createMesh({
        id: "greenLegMesh",
        geometryId: "myBoxGeometry",
        position: [4, -6, -4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
        color: [0.3, 1.0, 0.3]
    });

    sceneModel1.createEntity({
        id: "greenLeg",
        meshIds: ["greenLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel1.createMesh({
        id: "blueLegMesh",
        geometryId: "myBoxGeometry",
        position: [4, -6, 4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
        color: [0.3, 0.3, 1.0]
    });

    sceneModel1.createEntity({
        id: "blueLeg",
        meshIds: ["blueLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel1.createMesh({
        id: "yellowLegMesh",
        geometryId: "myBoxGeometry",
        position: [-4, -6, 4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
        color: [1.0, 1.0, 0.0]
    });

    sceneModel1.createEntity({ // Create object
        id: "yellowLeg",
        meshIds: ["yellowLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel1.finalize();

    //------------------------------------------------------------------------------------------------------------------
    // Second geometry model, containing table top
    //------------------------------------------------------------------------------------------------------------------

    const sceneModel2 = new SceneModel(viewer.scene, {
        id: "furniture2",
        isModel: true, // <--------------------- Represents a model, registers SceneModel by ID on viewer.scene.models
        position: [0, 0, 0],
        scale: [1, 1, 1],
        rotation: [0, 0, 0],
        edges: true
    });

    sceneModel2.createGeometry({
        id: "myBoxGeometry",
        primitive: "triangles",
        positions: [
            1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front
            1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v1 right
            1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v1-v6-v1 top
            -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left
            -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1,// v7-v4-v3-v2 bottom
            1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v1 back
        ],
        normals: [
            0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,// v0-v1-v2-v3 front
            1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,// v0-v3-v4-v5 right
            0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,// v0-v5-v6-v1 top
            -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,// v1-v6-v7-v2 left
            0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,// v7-v4-v3-v2 bottom
            0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1// v4-v7-v6-v5 back
        ],
        indices: [
            0, 1, 2, 0, 2, 3,            // front
            4, 5, 6, 4, 6, 7,            // right
            8, 9, 10, 8, 10, 11,         // top
            12, 13, 14, 12, 14, 15,      // left
            16, 17, 18, 16, 18, 19,      // bottom
            20, 21, 22, 20, 22, 23
        ]
    });

    sceneModel2.createMesh({
        id: "tableTopMesh",
        geometryId: "myBoxGeometry",
        position: [0, -3, 0],
        scale: [6, 0.5, 6],
        rotation: [0, 0, 0],
        color: [1.0, 0.3, 1.0]
    });

    sceneModel2.createEntity({ // Create object
        id: "tableTop",
        meshIds: ["tableTopMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel2.finalize();


    //------------------------------------------------------------------------------------------------------------------
    // First metadata model, containing elements for table and legs
    //------------------------------------------------------------------------------------------------------------------

    viewer.metaScene                            // This is the MetaScene for the Viewer
        .createMetaModel("furniture1", {         // Creates a MetaModel in the MetaScene
            "metaObjects": [                    // Creates MetaObjects in the MetaModel
                {
                    "id": "table",              // Does not match any Entity
                    "name": "Table",
                    "type": "furniture",        // Arbitrary type
                    "attributes": {             // Element attributes
                        "cost": "200"
                    }
                },
                {
                    "id": "redLeg",
                    "name": "Red table Leg",    // Same ID as red leg Entity
                    "type": "leg",
                    "parent": "table",          // References first MetaObject as parent
                    "attributes": {
                        "material": "wood"
                    }
                },
                {
                    "id": "greenLeg",           // Same ID as green leg Entity
                    "name": "Green table leg",
                    "type": "leg",
                    "parent": "table",
                    "attributes": {
                        "material": "wood"
                    }
                },
                {
                    "id": "blueLeg",            // Same ID as blue leg Entity
                    "name": "Blue table leg",
                    "type": "leg",
                    "parent": "table",
                    "attributes": {
                        "material": "wood"
                    }
                },
                {
                    "id": "yellowLeg",         // Same ID as yellow leg Entity
                    "name": "Yellow table leg",
                    "type": "leg",
                    "parent": "table",
                    "attributes": {
                        "material": "wood"
                    }
                }
            ]
        });

    //------------------------------------------------------------------------------------------------------------------
    // First metadata model, containing elements for table and top
    //------------------------------------------------------------------------------------------------------------------

    viewer.metaScene                            // This is the MetaScene for the Viewer
        .createMetaModel("furniture2", {         // Creates a MetaModel in the MetaScene
            "metaObjects": [                    // Creates MetaObjects in the MetaModel
                {
                    "id": "table",              // Does not match any Entity
                    "name": "Table",
                    "type": "furniture",        // Arbitrary type
                    "attributes": {             // Element attributes
                        "cost": "200"
                    }
                },
                {
                    "id": "tableTop",         // Same ID as purple table top Entity
                    "name": "Purple table top",
                    "type": "surface",
                    "parent": "table",
                    "attributes": {
                        "material": "formica",
                        "width": "60",
                        "depth": "60",
                        "thickness": "5"
                    }
                }
            ]
        });

    //------------------------------------------------------------------------------------------------------------------
    // Find SceneModel Entity's their model and object IDs
    //------------------------------------------------------------------------------------------------------------------

    // Get the whole table model
    const tableModel = viewer.scene.models["furniture"];

    // Get some leg objects
    const redLegObject = viewer.scene.objects["redLeg"];
    const greenLegObject = viewer.scene.objects["greenLeg"];
    const blueLegObject = viewer.scene.objects["blueLeg"];

    //------------------------------------------------------------------------------------------------------------------
    // Create a metadata structure tree view
    // This will show everything as a single tree
    //------------------------------------------------------------------------------------------------------------------

    const treeView = new TreeViewPlugin(viewer, {
        containerElement: document.getElementById("treeViewContainer"),
        autoExpandDepth: 1 // Initially expand root node
    });

    window.viewer = viewer;

</script>
</html>